;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;; lib begin ;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

__int_format:
    db "%ld", 0

__intln_format:
    db "%ld", 10, 0

;========== IO ==========
ALIGN 16
__lib_printInt:
    sub rsp, 8

    mov rsi, rdi
    mov rdi, __int_format
    xor rax, rax
    call printf

    add rsp, 8
    ret

ALIGN 16
__lib_printlnInt:
    sub rsp, 8

    mov rsi, rdi
    mov rdi, __intln_format
    xor rax, rax
    call printf

    add rsp, 8
    ret

ALIGN 16
getInt:
    sub rsp, 8

    mov rsi, rsp
    mov rdi, __int_format
    xor eax, eax
    call scanf
    call getchar
    mov rax, [rsp]

    add rsp, 8
    ret

; generated by gcc -O3
ALIGN   16
__lib_str_operator_add:
        push    r15
        push    r14
        mov     r15, rdi
        push    r13
        push    r12
        mov     r13, rsi
        push    rbp
        push    rbx
        sub     rsp, 8
        movsxd  rbx, dword [rdi-4H]
        movsxd  r12, dword [rsi-4H]
        lea     ebp, [rbx+r12]
        lea     edi, [rbp+1H]
        movsxd  rdi, edi
        add     rdi, 4
        call    malloc
        test    ebx, ebx
        mov     dword [rax], ebp
        mov     r14, rax
        lea     rbp, [rax+4H]
        jle     L_001
        lea     edx, [rbx-1H]
        mov     rsi, r15
        mov     rdi, rbp
        add     rdx, 1
        call    memcpy
L_001:  add     rbp, rbx
        test    r12d, r12d
        jle     L_002
        lea     edx, [r12-1H]
        lea     rdi, [r14+rbx+4H]
        mov     rsi, r13
        add     rdx, 1
        call    memcpy
L_002:  mov     byte [rbp+r12], 0
        mov     rax, rbp
        add     rsp, 8
        sub     rax, rbx
        pop     rbx
        pop     rbp
        pop     r12
        pop     r13
        pop     r14
        pop     r15
        ret

; generated by gcc -O3
ALIGN   16
__lib_str_substring:
        push    r14
        push    r13
        mov     r13, rsi
        push    r12
        push    rbp
        mov     r12, rdi
        push    rbx
        mov     ebx, edx
        sub     ebx, esi
        lea     edi, [rbx+2H]
        lea     ebp, [rbx+1H]
        movsxd  rdi, edi
        add     rdi, 4
        call    malloc
        test    ebp, ebp
        mov     r14, rax
        mov     dword [rax], ebp
        lea     rcx, [rax+4H]
        jle     L_003
        mov     edx, ebx
        lea     rsi, [r12+r13]
        mov     rdi, rcx
        add     rdx, 1
        call    memcpy
        mov     rcx, rax
L_003:  movsxd  rbp, ebp
        mov     rax, rcx
        pop     rbx
        mov     byte [r14+rbp+4H], 0
        pop     rbp
        pop     r12
        pop     r13
        pop     r14
        ret

; generated by gcc -O3
ALIGN   16
toString:
        push    rbx
        mov     rbx, rdi
        mov     edi, 16
        call    malloc
        test    rbx, rbx
        mov     r9, rax
        lea     rdi, [rax+4H]
        js      L_007
        jne     L_010
        lea     rcx, [rax+5H]
        mov     byte [rax+4H], 48
        mov     rsi, rcx
L_004:  mov     rax, rcx
        mov     byte [rcx], 0
        sub     rax, rdi
        mov     dword [r9], eax
        lea     rax, [rcx-1H]
        cmp     rax, rsi
        jc      L_006
L_005:  movzx   edx, byte [rsi]
        movzx   ecx, byte [rax]
        add     rsi, 1
        sub     rax, 1
        mov     byte [rsi-1H], cl
        mov     byte [rax+1H], dl
        cmp     rsi, rax
        jbe     L_005
L_006:  mov     rax, rdi
        pop     rbx
        ret
ALIGN   8
L_007:  lea     rsi, [rax+5H]
        mov     byte [rax+4H], 45
        neg     rbx
L_008:  mov     rcx, rsi
        mov     r8, qword 6666666666666667H
ALIGN   16
L_009:  mov     rax, rbx
        add     rcx, 1
        imul    r8
        mov     rax, rbx
        add     ebx, 48
        sar     rax, 63
        sar     rdx, 2
        sub     rdx, rax
        lea     eax, [rdx+rdx*4]
        add     eax, eax
        sub     ebx, eax
        mov     byte [rcx-1H], bl
        movsxd  rbx, edx
        test    rbx, rbx
        jnz     L_009
        jmp     L_004
ALIGN   8
L_010:  mov     rsi, rdi
        jmp     L_008


ALIGN 16
getString:
    push rbx
    sub rsp, 128

    mov rdi, rsp
    call gets

    mov rdi, rsp
    call strlen

    mov rbx, rax ; length
    lea rdi, [rax + 5]
    call malloc

    mov dword [rax], ebx ; store length

    lea rdi, [rax + 4]
    mov rsi, rsp
    call strcpy

    add rsp, 128
    pop rbx
    ret

ALIGN 16
__lib_str_length:
    mov eax, dword [rdi -4]

    ret

ALIGN 16
__lib_str_parseInt:
    sub rsp, 8

    mov rsi, __int_format
    mov rdx, rsp
    xor rax, rax
    call sscanf

    mov eax, dword [rsp]
    add rsp, 8
    ret

ALIGN 16
__lib_str_operator_lt:
    sub rsp, 8

    call strcmp
    cmp rax, 0
    setl al
    movzx rax, al

    add rsp, 8
    ret

ALIGN 16
__lib_str_operator_eq:
    sub rsp, 8

    call strcmp
    cmp rax, 0
    sete al
    movzx rax, al

    add rsp, 8
    ret

ALIGN 16
__lib_str_operator_ne:
    sub rsp, 8

    call strcmp
    cmp rax, 0
    setne al
    movzx rax, al

    add rsp, 8
    ret

ALIGN 16
__lib_str_operator_gt:
    sub rsp, 8

    call strcmp
    cmp rax, 0
    setg al
    movzx rax, al

    add rsp, 8
    ret


ALIGN 16
__lib_array_size:
    mov eax, dword [rdi -4]

    ret

ALIGN 16
__lib_str_ord:
    xor rax, rax
    mov al, byte [rdi + rsi]

    ret

ALIGN 16
print:
    sub rsp, 8

    xor rax, rax
    call printf

    add rsp, 8
    ret

ALIGN 16
println:
    sub rsp, 8

    call puts

    add rsp, 8
    ret
